package com.brycen.nio.buffer;

import org.junit.Test;

import java.nio.ByteBuffer;

public class BufferTest {
    /**
     * 缓存区分类：
     * ByteBuffer、IntBuffer、LongBuffer、StringBuffer、ShortBuffer、FloatBuffer、DoubleBuffer
     */

    @Test
    public void test1(){
        //1、分配一个缓冲区，容量为10
        ByteBuffer byteBuffer = ByteBuffer.allocate(10);
        System.out.println("当前位置："+byteBuffer.position());  //0
        System.out.println("限制位置："+byteBuffer.limit());     //10
        System.out.println("缓冲大小："+byteBuffer.capacity());  //10
        System.out.println("-------------------------");
        //2、使用put，往缓冲区添加数据
        String name = "brycen";
        byteBuffer.put(name.getBytes());
        System.out.println("当前位置："+byteBuffer.position());  //6，前面写入了6个数据，所以下面需要从角标6上开始写入
        System.out.println("限制位置："+byteBuffer.limit());     //10，表示在缓冲区里，只能操作10个字节
        System.out.println("缓冲大小："+byteBuffer.capacity());  //10
        System.out.println("-------------------------");
        //3、使用flip，将缓冲区的界限设置为当前位置，并将当前位置设置为0，就是归位的意思
        byteBuffer.flip();
        System.out.println("当前位置："+byteBuffer.position());  //0，转为可读模式，从0角标开始读取
        System.out.println("限制位置："+byteBuffer.limit());     //6，表示在缓冲区里，角标6以及往后是不能使用的，也可以表示缓冲区中有多少个数据
        System.out.println("缓冲大小："+byteBuffer.capacity());  //10
        System.out.println("-------------------------");
        //4、使用get读取缓冲区数据，默认读取position位置的数据，读取过后，position位置往后移动
        char ch = (char) byteBuffer.get();
        System.out.println(ch);
        System.out.println("当前位置："+byteBuffer.position());  //1，转为可读模式，从0角标开始读取
        System.out.println("限制位置："+byteBuffer.limit());     //6，表示在缓冲区里，角标6以及往后是不能使用的，也可以表示缓冲区中有多少个数据
        System.out.println("缓冲大小："+byteBuffer.capacity());  //10
    }

    @Test
    public void test2() {
        ByteBuffer byteBuffer = ByteBuffer.allocate(10);
        String name = "brycen";
        byteBuffer.put(name.getBytes());
        System.out.println("当前位置：" + byteBuffer.position());  //6
        System.out.println("限制位置：" + byteBuffer.limit());     //10
        System.out.println("缓冲大小：" + byteBuffer.capacity());  //10
        System.out.println("-------------------------");
        //使用clear清除缓冲区，这里的清除其实只是将position置为0，限制位置重置，其实里面的内容还是存在的
        byteBuffer.clear();
        System.out.println("当前位置：" + byteBuffer.position());  //0
        System.out.println("限制位置：" + byteBuffer.limit());     //10
        System.out.println("缓冲大小：" + byteBuffer.capacity());  //10
        System.out.println("-------------------------");
        char ch = (char) byteBuffer.get();
        System.out.println(ch);//清除后再获取也是能获取的旧的数据的，所以clear只是重置里position
        System.out.println(byteBuffer.position());//获取数据后position往后移

    }
    @Test
    public void test3() {
        //使用mark标记位置，然后使用reset恢复刚才标记的位置
        ByteBuffer buf = ByteBuffer.allocate(10);
        String name = "brycen";
        buf.put(name.getBytes());
        System.out.println("当前位置："+buf.position());  //6
        System.out.println("限制位置："+buf.limit());     //10
        System.out.println("缓冲大小："+buf.capacity());  //10
        System.out.println("-------------------------");
        //缓冲区当前位置归位
        buf.flip();
        byte[] data1 = new byte[2];
        buf.get(data1);
        System.out.println(new String(data1));
        System.out.println("当前位置："+buf.position());  //2
        System.out.println("限制位置："+buf.limit());     //6
        System.out.println("缓冲大小："+buf.capacity());  //10
        System.out.println("-------------------------");

        //标记当前位置
        buf.mark();

        byte[] data2 = new byte[2];
        buf.get(data2);
        System.out.println(new String(data2));
        System.out.println("当前位置："+buf.position());  //4
        System.out.println("限制位置："+buf.limit());     //6
        System.out.println("缓冲大小："+buf.capacity());  //10
        System.out.println("-------------------------");

        //回到之前mark的位置
        buf.reset();
        //判断是否还有数据
        if (buf.hasRemaining()){
            //输出剩余数据的数量
            System.out.println(buf.remaining());
        }
    }

    /**
     * 缓冲区分为两种：直接内存、非直接内存
     * 直接内存：就是操作系统本地I/O的内存，优点：直接与本地I/O操作，性能上更优；缺点：创建消耗更大。适用于传输数据大、周期长的场景
     * 非直接内存：使用的是堆内存，就是我们应用的堆内存，优缺点和上面相反。适用于无性能要求的场景
     * 非直接内存流程：本地I/O->直接内存->非直接内存->直接内存->本地I/O
     * 直接内存流程：本地I/O->直接内存->本地I/O
     */
    @Test
    public void test4() {
        //创建直接内存缓冲区
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024);
        //判断是否是直接内存缓冲区
        System.out.println(byteBuffer.isDirect());
    }
}
